<?php
namespace app\service;

use app\common\enum\ScopeEnum;
use app\common\enum\TokenEnum;
use app\facade\Redis;
use think\Exception;
use think\facade\Request;

class Token {

    public function __construct() {

    }

    /**
     * 生成令牌
     * @return string
     */
    public function generateToken()
    {
        $randChar = getRandChar(32);
        $timestamp = $_SERVER['REQUEST_TIME_FLOAT'];
        $tokenSalt = TokenEnum::Salt;
        return md5(md5($randChar . $timestamp ). $tokenSalt);
    }

    /**
     * 生成令牌
     * @return string
     */
    public function generateTokenOpenid($openid = "")
    {
        $randChar = getRandChar(32);
        $timestamp = $_SERVER['REQUEST_TIME_FLOAT'];
        $tokenSalt = TokenEnum::Salt;
        return md5(md5($randChar . $timestamp ). $tokenSalt . $openid);
    }


    /**
     * @return bool
     */
    public function needPrimaryScope()
    {
        $scope = $this->getCurrentTokenVar('scope');
        return $scope === ScopeEnum::USER;
    }

    /**
     * 普通用户
     * @return bool
     */
    public function needExclusiveScope()
    {
        $scope = $this->getCurrentTokenVar('scope');
        return $scope === ScopeEnum::USER;
    }

    /**
     * 后台管理员操作权限认证
     * @return bool
     */
    public function needSuperScope()
    {
        $scope = $this->getCurrentTokenVar('scope');
        if (!empty($scope) && in_array($scope, [ScopeEnum::SUPER, ScopeEnum::DEVELOPER]) )
        {
            return true;
        }
        return false;
    }


    /**
     * 供应商
     * @return bool
     */
    public function needSupplierScope()
    {
        $scope = $this->getCurrentTokenVar('scope');
        return $scope === ScopeEnum::SUPPLIER;
    }

    /**
     * 取登录指定KEY值
     * @param $key
     * @return bool|string
     */
    public function getCurrentTokenVar($key) {
        $token = Request::header('Authorization');
        $vars = Redis::get($token);
        is_object($vars) && $vars = $vars->toArray();
        if (!empty($vars) && array_key_exists($key, $vars))
        {
            return $vars[$key];
        }
        return false;
    }

    /**
     * 取当前登录用户的所有信息
     * @return mixed
     */
    public function getCurrentUserInfo()
    {
        return Redis::get(Request::header('Authorization'));
    }


    /**
     * 从缓存中获取当前用户指定身份标识
     * @param $keys
     * @return array|bool
     */
    public function getCurrentIdentity($keys)
    {
        $token = Request::header('Authorization');
        $identities = Redis::get($token);
        is_object($identities) && $identities = $identities->toArray();
        if (!empty($identities))
        {
            $result = [];
            foreach ($keys as $key)
            {
                if (array_key_exists($key, $identities))
                {
                    $result[$key] = $identities[$key];
                }
            }
            return $result;
        }
        return false;
    }

    /**
     * 当需要获取全局UID时，应当调用此方法 而不应当自己解析UID
     *
     */
    public function getCurrentUid() {
        $uid = $this->getCurrentTokenVar('id');
        $scope = $this->getCurrentTokenVar('scope');
        if ($scope == ScopeEnum::SUPER) {
            // 只有Super权限才可以自己传入uid
            // 且必须在get参数中，post不接受任何uid字段
            $userID = input('get.uid');
            if (!$userID) {
                return false;
            }
            return $userID;
        }
        return $uid;
    }

    /**
     * 检查操作UID是否合法
     * @param $checkedUID
     * @return bool
     */
    public function isValidOperate($checkedUID) {
        if(!$checkedUID)
        {
            return false;
        }
        $currentOperateUID = $this->getCurrentUid();
        return $currentOperateUID === $checkedUID;
    }

    public function verifyToken($token)
    {
        $exist = Redis::get($token);
        if(empty($exist)) $exist = Redis::get($token);
        if ($exist) {
			$result = Redis::set($token, $exist, TokenEnum::Expire);
            if (!$result){
                return false;
            }
        }
        return $exist ? true : false;
    }

    public function toDo()
    {
        return 'zzz';
    }
}